/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Cards;

import java.util.Objects;

/**
 * Class FrenchCard. It can use to manage FrenchCard
 * @author masterinftel11
 */
public class FrenchCard extends Card implements Comparable<FrenchCard>{
    private final Number rank;
    private final Suit suit;
 
    /**
     * Manage symbolA to FrenchCard. Number of Card. It can be ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING.
     */
    public enum Number implements SymbolA{
        ACE(1),TWO(2),THREE(3),FOUR(4),FIVE(5),SIX(6),SEVEN(7),
        EIGHT(8),NINE(9),TEN(10),JACK(11),QUEEN(12),KING(13);
        
        private final int code;
        
        /**
         * Returns the code of the Number we are working with
         * @return code
         */
        public int getCode() {
            return code;
        }
        
        /**
         * Constructor of this enumeration
         * @param code the code to initialize 
         */
        private Number(int code) {
            this.code = code;
        }
        
        /**
         * Static method that returns the number associated to a code
         * @param code code from which we want to get the number of
         * @return the number associated to the code 
         */
        public static Number valueOf(int code) {
            for (Number rank: Number.values()) {
                if (rank.getCode()==code)
                    return rank;
            }
            throw new RuntimeException("INVALID CODE");
        }
    }
    
    /**
     * Manage symbolB to FrenchCard. It can be SPADES, HEARTS, CLUBS, DIAMONDS.
     */
    public enum Suit implements SymbolB{
        SPADES(1),HEARTS(2),CLUBS(3),DIAMONDS(4);
        
        private final int code;
        
        /**
         * Returns the code of the Suit we are working with
         * @return code
         */
        public int getCode() {
            return code;
        }
        
        /**
         * Constructor of this enumeration
         * @param code the code to initialize 
         */
        private Suit(int code) {
            this.code = code;
        }
        
        /**
         * Static method that returns the suit associated to a code
         * @param code code from which we want to get the suit of
         * @return the suit associated to the code 
         */
        public static Suit valueOf(int code) {
            for (Suit suit: Suit.values()) {
                if (suit.getCode()==code)
                    return suit;
            }
            throw new RuntimeException("INVALID CODE");
        }

    }
    
    /**
     * Method to initialize FrenchCard through value of rank and suit
     * @param rank of card
     * @param suit or cark
     */
    public FrenchCard(int rank,int suit) {
        this.suit = Suit.valueOf(suit);
        this.rank = Number.valueOf(rank);
    }
    
     /**
     * Method to initialize FrenchCard through of rank and suit
     * @param rank of card
     * @param suit or cark
     */
    public FrenchCard(Number rank, Suit suit) {
        this.suit = suit;
        this.rank = rank;
    }
    
    /**
     * Method to get rank
     * @return rank
     */
    public Number getRank() {
        return rank;
    }
    
    /**
     * Method to set suit
     * @return suit
     */
    public Suit getSuit() {
        return suit;
    }
    
    /**
     * Method to get points
     * @return points
     */
    public int points(){
        int points;
        if (this.getRank().equals(Number.JACK) ||  this.getRank().equals(Number.QUEEN) ||  this.getRank().equals(Number.KING)){
            points = 10;
        }
        else if (this.getRank().equals(Number.ACE)){
            points = 11;
        }
        else {
            points = this.getRank().getCode();
        }
        return points;
    }
    
    /**
     * Method to compare two FrenchCards
     * @param o object that we'll compare to the 'this' object
     * @return 1 if this > o, 0 if equals, -1 if this < o.
     */
    @Override
    public int compareTo(FrenchCard o) {
        if (this.getSuit().getCode() < o.getSuit().getCode()){
            return -1;
        }
        else if (this.getSuit().getCode() == o.getSuit().getCode()){
            if (this.getRank().getCode() < o.getRank().getCode()){
                return -1;
            }
            else if (this.getRank().getCode() == o.getRank().getCode()){
                return 0;
            }
            else {
                return 1;
            }
        }
        else
            return 1;
    }

    /**
     * Hashcode asociated to this enum, necesary to run equals function
     * @return the hashcode itself
     */
    @Override
    public int hashCode() {
        int hash = 7;
        hash = 67 * hash + Objects.hashCode(this.rank);
        hash = 67 * hash + Objects.hashCode(this.suit);
        return hash;
    }

    /**
     * Function that determinates if two objects are equals
     * @param obj object that we'll compare to 'this'
     * @return true if equals, false if not
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final FrenchCard other = (FrenchCard) obj;
        if (this.rank != other.rank) {
            return false;
        }
        return this.suit == other.suit;
    }
    /**
     * Method that returns the string associated to this FrenchCard
     * @return The string associated to 'this'
     */
    @Override
    public String toString(){
        return rank.toString() + " " + suit.toString();
    }
}
